/*
 *                  BioJava development code
 *
 * This code may be freely distributed and modified under the
 * terms of the GNU Lesser General Public Licence.  This should
 * be distributed with the code.  If you do not have a copy,
 * see:
 *
 *      http://www.gnu.org/copyleft/lesser.html
 *
 * Copyright for this code is held jointly by the individual
 * authors.  These should be listed in @author doc comments.
 *
 * For more information on the BioJava project and its aims,
 * or to join the biojava-l mailing list, visit the home page
 * at:
 *
 *      http://www.biojava.org/
 * 
 * Created on Jul 2, 2007
 * 
 */

package org.biojava.services.das.servlets;

import java.awt.Image;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.biojava.dasobert.dasregistry.DasSource;
import org.biojava.services.das.dao.ProjectBean;
import org.biojava.services.das.dao.RegistryUser;
import org.biojava.services.das.registry.DasRegistrySql;
import org.biojava.services.das.registry.UserManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ProjectActionServlet extends HttpServlet {

	public static  String SHOWMYPROJECTS   = "listProjects.jsp?cmd=showmine";
	public static  String ADDSOURCEPROJECT = "addSourceProject.jsp?";
	public static  String PROJECTDETAILS   = "showProjectDetails.jsp";
	public static  String EDITPROJECT      = "editProject.jsp";
	public static final String LOGIN       = "login.jsp";

	/**
	 * 
	 */
	private static final long serialVersionUID = -5110926701588725813L;

	public void init() throws ServletException {
		// TODO Auto-generated method stub
		super.init();		
	}

	public void doGet(
			HttpServletRequest req,
			HttpServletResponse resp
	)
	throws ServletException, IOException
	{	

	}

	public void doPost(HttpServletRequest req, HttpServletResponse res)
	throws ServletException,IOException{

		HttpSession session=req.getSession(true);
		String email = (String) session.getAttribute("email");
		if (email == null) {
			(req.getRequestDispatcher(LOGIN)).forward(req,res);
			return;
		}
		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
		UserManager manager=(UserManager)ctx.getBean("userManager");
		//UserManager manager = new UserManager();
		RegistryUser user = manager.getUser(email);

		if (user == null) {
			String message = "could not identify user " + email;
			req.setAttribute("message", message);
			req.getRequestDispatcher(LOGIN).forward(req,res);	
			return;
		}


		String action = req.getParameter("action");

		System.out.println("action :>"+action+"<");

		if ( action == null) {
			boolean isMultipart = ServletFileUpload.isMultipartContent(req);
			if ( isMultipart) {
				System.out.println("is multipart");

				int project_id = updateProject(user,manager,req);
				req.getRequestDispatcher(PROJECTDETAILS+"?project_id="+project_id).forward(req,res);
				return;
			}

			req.getRequestDispatcher(SHOWMYPROJECTS).forward(req,res);
			return;
		}
		if ( action.equals("add")){
			req.getRequestDispatcher(ADDSOURCEPROJECT).forward(req,res);
			return;
		}



		// ALL ACTIONS BELOW THIS POINT REQUIRE A PROJECT ID

		String[] projectIDS = req.getParameterValues("projectID");

		if ( projectIDS == null){
			req.getRequestDispatcher(SHOWMYPROJECTS).forward(req,res);
			return;
		}
		if ( action.equals("delete")){
			deleteProjects(projectIDS, manager);		
		} else if ( action.equals("edit")){
			req.getRequestDispatcher(EDITPROJECT).forward(req,res);
			return;
		} else if (action.equals("addsource")){

			String[] sources = req.getParameterValues("DS_ID");
			int project_id = addDasSources(projectIDS,sources,user,manager);
			req.getRequestDispatcher(PROJECTDETAILS+"?project_id="+project_id).forward(req,res);
			return;		

		} else if ( action.equals("remove")){
			String[] sources = req.getParameterValues("DS_ID");
			removeDasSources(sources,user,manager);

			if ( projectIDS.length >0){

				try {
					int project_id = Integer.parseInt(projectIDS[0]);
					req.getRequestDispatcher(PROJECTDETAILS+"?project_id="+project_id).forward(req,res);
					return;
				} catch(Exception e){

				}

			}
		}

		req.getRequestDispatcher(SHOWMYPROJECTS).forward(req,res);

	}


	private int updateProject(
			RegistryUser user, 
			UserManager manager,
			HttpServletRequest request ){

		System.out.println("update project");

		Map data = processProjectData(request);

		ProjectBean newProject = (ProjectBean) data.get("project"); 
		Image img = (Image)data.get("image");

		ProjectBean project = manager.getProjectById(newProject.getProjectID());
		int project_id = newProject.getProjectID();

		// only the project owner can proceed.
		if (! user.equals(project.getOwner())){
			return project_id;

		}

		newProject.setProjectID(project_id);

		manager.updateProject(newProject);


		if (img != null)
			manager.writeProjectImage(project, img,FileUploadServlet.DEFAULT_IMAGE_FORMAT);

		return project_id;
	}

	private Map processProjectData(HttpServletRequest request){
		ProjectBean p = new ProjectBean();
		Image image = null;

		boolean isMultipart = ServletFileUpload.isMultipartContent(request);

		Map ret = new HashMap();
		if ( ! isMultipart ) {			
			return ret ;

		}

		DiskFileItemFactory factory = new DiskFileItemFactory();


//		Create a new file upload handler
		ServletFileUpload upload = new ServletFileUpload(factory);
		List items = new ArrayList();
		try {
			items = upload.parseRequest(request);


		} catch (Exception e){
			e.printStackTrace();

			// ignore problem

			return ret;
		}
		Iterator iter = items.iterator();

		while (iter.hasNext()) {
			FileItem item = (FileItem) iter.next();
			if (item.isFormField()) {

				String name = item.getFieldName();
				String value = item.getString();

				if ( value == null)
					continue;
				if (value.equals(""))
					continue;

				if (name.equals("projectName"))

					p.setName(value);

				if ( name.equals("projectUrl")) {
					try {
						URL u = new URL(value);
						p.setHomepage(u);
					} catch (MalformedURLException e){						
					}								
				}


				if ( name.equals("projectDesc")) 
					p.setDescription(value);

				if ( name.equals("projectID")){
					try {
						int project_id = Integer.parseInt(value);
						p.setProjectID(project_id);
					} catch (NumberFormatException ex){}

				}
				
				if ( name.equals("file")){
					System.err.println("did not detect file as multipart form!");
				}

			} else {
				Image tmp = getImage(item);
				if ( tmp != null) {
					// got an image!
					image = tmp;
				}

			}



		}


		ret.put("project",p);
		ret.put("image", image);
		return ret;

	}

	private Image getImage(FileItem item){

		System.out.println("getImage");
		
		DiskFileItem ditem = null;
		if (! item.isFormField()) {


			String fieldName = item.getFieldName();
			String fileName = item.getName();
			String contentType = item.getContentType();
			System.out.println(fieldName);
			boolean isInMemory = item.isInMemory();
			long sizeInBytes = item.getSize();
			if ( fileName.equals("")){
				System.out.println("filename == ''");
				return null;
			}
			System.out.println(fieldName + " >" + 
					fileName + "< " + 
					contentType + " " +
					isInMemory + " " + sizeInBytes);
			//TODO: resize the  image, store in DB

			if ( item instanceof DiskFileItem){
				ditem = (DiskFileItem)item;
			}
		}



		if ( ditem == null)  {
			System.out.println("ProjectActionServlet: ditem==null");
			return null;
		}
		try {
			System.out.println("reading stream");
			Image image    = ImageIO.read(ditem.getInputStream());

			ditem.delete();
			if ( image != null) {
				Image newImage = ImageUtil.scaleImage(FileUploadServlet.IMAGE_HEIGHT, image);
				return newImage;
			}
		} catch (IOException e){
			e.printStackTrace();
		}
		System.out.println("did not get image...");
		return null;

	}

	private void removeDasSources(String[] DS_IDS, RegistryUser user,
			UserManager manager){


		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
		DasRegistrySql registry=(DasRegistrySql)ctx.getBean("registryBean");



		List sources = new ArrayList();
		for (int i=0; i < DS_IDS.length;i++ ){
			String DS_ID = DS_IDS[i];
			DasSource ds = registry.getDasSource(DS_ID);

			int auto_id = registry.getAutoID4DasSource(ds);

			if ( ! manager.isOwner(user,auto_id) ){					
				continue;
			}

			sources.add(new Integer(auto_id));

		}

		try {				

			Iterator iter = sources.iterator();

			while (iter.hasNext()){
				Integer auto_id = (Integer) iter.next();

				manager.removeDasSourceFromProject(auto_id.intValue());
			}


		} catch (Exception e){
			e.printStackTrace();
		}



		return ;
	}

	private int addDasSources(String[] projectIDS, String[] DS_IDS, RegistryUser user,
			UserManager manager){

		int project_id = -1;

		BeanFactory ctx=(new ClassPathXmlApplicationContext("SpringDAO.xml"));
		DasRegistrySql registry=(DasRegistrySql)ctx.getBean("registryBean");
		if (projectIDS.length == 1){
			String projectID= projectIDS[0];

			List sources = new ArrayList();
			for (int i=0; i < DS_IDS.length;i++ ){
				String DS_ID = DS_IDS[i];
				DasSource ds = registry.getDasSource(DS_ID);




				int auto_id = registry.getAutoID4DasSource(ds);

				if ( ! manager.isOwner(user,auto_id) ){					
					continue;
				}

				sources.add(new Integer(auto_id));

			}

			try {
				project_id = Integer.parseInt(projectID);
				ProjectBean project = manager.getProjectById(project_id);
				Iterator iter = sources.iterator();

				while (iter.hasNext()){
					Integer auto_id = (Integer) iter.next();

					manager.addDasSource2Project(project,auto_id.intValue());
				}


			} catch (Exception e){
				e.printStackTrace();
			}
		}
		return project_id;
	}

	private void deleteProjects(String[] projectIDS, UserManager manager){
		
		for (int i = 0; i < projectIDS.length; i++) {
			String projectID = projectIDS[i];	
			try{
				int project_id = Integer.parseInt(projectID);
				ProjectBean project = manager.getProjectById(project_id);
				manager.deleteProject(project);

			} catch (NumberFormatException e){
				e.printStackTrace();
			}
		}
	}
}
